package ro.upt.ac.cstaicu.execution;

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipInputStream;

public class ImprovedJarReader {

	private Hashtable<String, Integer> classSizes = new Hashtable<String, Integer>();
	private Hashtable<String, byte[]> classesContent = new Hashtable<String, byte[]>();

	private String jarFileName;

	public ImprovedJarReader(String jarFileName) throws IOException {
		this.jarFileName = jarFileName;
		init();

	}

	private void init() throws IOException {
		ZipFile zf;
		zf = new ZipFile(jarFileName);
		Enumeration<? extends ZipEntry> e = zf.entries();
		while (e.hasMoreElements()) {
			ZipEntry ze = (ZipEntry) e.nextElement();
			classSizes.put(ze.getName(), new Integer((int) ze.getSize()));
		}
		zf.close();		
	}

	public byte[] getResource(String name) {
		if (!classSizes.keySet().contains(name))
			return null;
		if (classesContent.keySet().contains(name))
			return classesContent.get(name);
		return readClass(name);
	}

	private byte[] readClass(String name) {
		try {
			int size = (int) classSizes.get(name);

			if (size == -1) {
				return null;
			}

			byte[] b = new byte[(int) size];

			FileInputStream fis;
			fis = new FileInputStream(jarFileName);
			BufferedInputStream bis = new BufferedInputStream(fis);
			ZipInputStream zis = new ZipInputStream(bis);
			ZipEntry ze = null;
			while ((ze = zis.getNextEntry()) != null) {

				if (ze.isDirectory()) {
					continue;
				}

				if (ze.getName().equals(name)) {

					int rb = 0;
					int chunk = 0;
					
					while (((int) size - rb) > 0) {
						chunk = zis.read(b, rb, (int) size - rb);
						if (chunk == -1) {
							break;
						}
						rb += chunk;
					}
					bis.close();
					classesContent.put(name, b);
					return b;

				}
			}
			bis.close();
			return null;
		} catch (IOException e) {
			return null;
		}

	}

}
